<template>
  <div ref="container" class="graph-container"></div>
</template>

<script lang="ts" setup>
import {onMounted, ref, watch} from "vue";

import {Cell, Graph} from "@antv/x6";

Graph.registerNode(
    'activity',
    {
      inherit: 'rect',
      markup: [
        {
          tagName: 'rect',
          selector: 'body',
        },
        {
          tagName: 'text',
          selector: 'label',
        },
      ],
      attrs: {
        body: {
          rx: 6,
          ry: 6,
          stroke: '#5F95FF',
          fill: '#EFF4FF',
          strokeWidth: 1,
        },
      },
    },
    true,
)

Graph.registerNode(
    'gateway',
    {
      inherit: 'polygon',
      attrs: {
        body: {
          refPoints: '0,10 10,0 20,10 10,20',
          strokeWidth: 1,
          stroke: '#5F95FF',
          fill: '#EFF4FF',
        },
      },
    },
    true,
)

Graph.registerEdge(
    'z-edge',
    {
      inherit: 'edge',
      attrs: {
        line: {
          stroke: '#A2B1C3',
          strokeWidth: 2,
        },
      },
    },
    true,
)

const emits = defineEmits([
  "exportPNG"
]);
const props = defineProps({
  nodeData: {
    type: Array,
    default: () => {
      return [];
    },
  },
  edgeData: {
    type: Array,
    default: () => {
      return [];
    },
  },
  alias: {
    type: Object,
    default: () => {
      return {
        name: "name",
        type: "type",
        left: 'left',
        right: 'right',
        center: 'center',
        source: "source",
        target: "target",
        parent: "parentId",
        id: "id",
        style: 0,
      };
    },
  }
});

const container = ref<HTMLDivElement | null>(null);

let graph: Graph | null = null;

watch(
    () => props.nodeData,
    () => {
      setView(props.nodeData, true);
    },
);

onMounted(() => {
  setView(props.nodeData);
});

const delay = (ms) => {
  return new Promise(resolve => {
    setTimeout(resolve, ms); // 内部仍然使用setTimeout，但封装在Promise中
  });
}

const setView = async (nodes, isRestart = false) => {
  if (container.value) {
    if (!isRestart) {
      graph = new Graph({
        container: container.value,
        scroller: true,
        interacting: false,
        connecting: {
          router: 'manhattan',
          // router: 'metro',
        },
        background: {
          color: '#f7faff'
        },
        grid: true,
        embedding: {
          enabled: true,
        },
        translating: {
          restrict(view) {
            const cell = view.cell
            if (cell.isNode()) {
              const parent = cell.getParent()
              if (parent) {
                return parent.getBBox()
              }
            }

            return null
          },
        },
        // 不能同时使用scroller和panning 两种形式在交互上有冲突
        // panning: {
        //   enabled: true,
        //   modifiers: [],
        //   eventTypes: ['leftMouseDown'],
        // },
      });
    }

    if (graph && isRestart) {

    } else if (graph) {
      let data = props.nodeData

      let leftArr = []
      let rightArr = []
      let centerArr = []

      data.forEach(item => {
        item['zIndex'] = 10
        item['position'] = {
          x: 0,
          y: 0,
        }
        if (typeof item[props.alias.type] !== "undefined") {
          item['width'] = 100
          item['height'] = 60
        } else {
          item["shape"] = "z-edge"
        }
        if (item[props.alias.type] === props.alias.left) {
          leftArr.push(item)
          item["shape"] = "activity"
          item['position']['x'] = 60
          item['position']['y'] = 60 * leftArr.length + (leftArr.length * 20)
        } else if (item[props.alias.type] === props.alias.right) {
          rightArr.push(item)
          item["shape"] = "activity"
          item['position']['x'] = 670
          item['position']['y'] = 60 * rightArr.length + (rightArr.length * 20)
        }else if (item[props.alias.type] === props.alias.center) {
          centerArr.push(item)
          item['shape'] = 'gateway'
          item['position']['x'] = 390
          item['position']['y'] = 60 * centerArr.length + (centerArr.length * 60)
        }
      })

      // data = data.map(item => {
      //   if (item[props.alias.type] === props.alias.center) {
      //     item['shape'] = 'gateway'
      //     item['position']['x'] = 390
      //     item['position']['y'] = 60 * center.length + (center.length * 40)
      //   }
      //   return item
      // })


      const cells: Cell[] = []
      data.forEach((item: any) => {
        if (item.shape === 'z-edge') {
          cells.push(graph.createEdge(item))
        } else {
          cells.push(graph.createNode(item))
        }
      })
      graph.resetCells(cells)
      graph.zoomToFit({padding: 10, maxScale: 1})

      // setupListeners();

      graph.addNode({
        x: 40,
        y: 40,
        width: 150,
        height: leftArr.length * (60 + 20) + 40,
        zIndex: 1,
        label: '输入',
        attrs: {
          label: {
            refY: 0,
            fontSize: 12,
          },
          body: {
            fill: '#fffbe6',
            stroke: '#ffe7ba',
          },
        },
      })


      graph.addNode({
        x: 640,
        y: 40,
        width: 150,
        height: rightArr.length * (60 + 20) + 40,
        zIndex: 1,
        label: '输出',
        attrs: {
          label: {
            refY: 0,
            fontSize: 12,
          },
          body: {
            fill: '#fffbe6',
            stroke: '#ffe7ba',
          },
        },
      })
      //
      // layoutGraph();
      graph.zoomTo(0.8);
      graph.centerContent();
    }

    if (graph) {
      await delay(1000);
      graph.toPNG(
          (dataUri: string) => {
            // 下载
            // DataUri.downloadDataUri(dataUri, 'chartx.png');
            // console.log(dataUri)
            emits('exportPNG', dataUri)
          },
          {
            backgroundColor: 'white',
            padding: {
              top: 20,
              right: 30,
              bottom: 40,
              left: 50,
            },
            copyStyles: true,
            quality: 1,
          }
      );

    }
  }
};
</script>

<style lang="scss" scoped>
.graph-container {
  width: 100%;
  height: 100%;

  .x6-cell {
    cursor: default;
  }

  .x6-node .btn {
    cursor: pointer;
  }
}
</style>
